package com.virus.server.utils;

import com.virus.server.catalina.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ServerXmlUtils {

    private static Document document;

    private static Map<String, Context> contextMap;

    static {
        String server = null;
        try {
            server = FileUtils.readUTF8(Constant.serverXml);
        } catch (IOException e) {
            e.printStackTrace();
        }
        document = Jsoup.parse(server);
    }

    public static List<Service> parseService() {
        List<Service> services = new ArrayList<>();
        Elements elements = document.select("Service");
        for (Element element : elements) {
            String name = element.attr("name");
            Service service = new Service(name);
            Engine engine = parseEngine(element);
            service.setEngine(engine);
            List<Connector> connectors = parseConnector(element, service);
            service.setConnectors(connectors);
            services.add(service);
        }
        return services;
    }

    private static List<Connector> parseConnector(Element elmService, Service service) {
        List<Connector> connectors = new ArrayList<>();
        Elements elements = elmService.select("Connector");
        for (Element element : elements) {
            String port = element.attr("port");
            Connector connector = new Connector(Integer.parseInt(port), service);
            connectors.add(connector);
        }
        return connectors;
    }

    private static Engine parseEngine(Element service) {
        Element element = service.select("Engine").first();
        String name = element.attr("name");
        String defaultName = element.attr("defaultName");
        List<Host> hosts = parseHost(element);
        Engine engine = new Engine(name, defaultName);
        engine.setHosts(hosts);
        return engine;
    }

    private static List<Host> parseHost(Element engine) {
        List<Host> hosts = new ArrayList<>();
        Elements elements = engine.select("Host");
        for (Element element : elements) {
            String name = element.attr("name");
            String appBase = element.attr("appBase");
            Host host = new Host(name);
            host.setAppBase(appBase);
            List<Context> contexts = parseContext(element);
            List<Context> appBaseList = scanContextOfAppBase(host);
            List<Context> combine = new ArrayList<>();
            combine.addAll(contexts);
            if (appBaseList != null) {
                combine.addAll(appBaseList);
            }
            host.setContexts(combine);
            contextMap = host.getContextMap();
            hosts.add(host);
        }
        return hosts;
    }

    private static List<Context> parseContext(Element host) {
        List<Context> contexts = new ArrayList<>();
        Elements elements = host.select("Context");
        for (Element element : elements) {
            String path = element.attr("path");
            String docBase = element.attr("docBase");
            Context context = new Context(path, docBase);
            contexts.add(context);
        }
        return contexts;
    }

    private static List<Context> scanContextOfAppBase(Host host) {
        List<Context> contexts = new ArrayList<>();
        String appBase = host.getAppBase();
        File appBaseFile = new File(appBase);
        if (!appBaseFile.exists()) {
            appBaseFile = new File(System.getProperty("user.dir"), appBase);
        }
        File[] files = appBaseFile.listFiles();
        if (files == null) {
            return null;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                String path = file.getName();
                if (path.equals("ROOT")) {
                    path = "";
                }
                path = "/" + path;
                String docBase = file.getAbsolutePath();
                Context context = new Context(path, docBase);
                contexts.add(context);
            }
        }
        return contexts;
    }

    public static Map<String, Context> getContextMap() {
        return contextMap;
    }
}
